package com.yc.music.utils;

import ohos.app.Context;
import ohos.data.DatabaseHelper;
import ohos.data.preferences.Preferences;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * MusicSpUtils
 *
 * @since 2021-05-10
 */
public final class MusicSpUtils {
    private static HashMap<String, MusicSpUtils> SP_UTILS_MAP = new HashMap<>();
    private static Context context;
    private Preferences sp;

    private MusicSpUtils(final String spName) {
        sp = new DatabaseHelper(context).getPreferences(spName);
    }

    /**
     * 初始化
     *
     * @param application 上下文
     */
    public static void init(Context application) {
        context = application;
    }

    /**
     * 获取 SP 实例
     *
     * @return {@link MusicSpUtils}
     */
    public static MusicSpUtils getInstance() {
        return getInstance("");
    }

    /**
     * 获取 SP 实例
     *
     * @param spName sp 名
     * @return {@link MusicSpUtils}
     */
    public static MusicSpUtils getInstance(String spName) {
        if (isSpace(spName)) {
            spName = "spUtils";
        }
        MusicSpUtils spUtils = SP_UTILS_MAP.get(spName);
        if (spUtils == null) {
            spUtils = new MusicSpUtils(spName);
            SP_UTILS_MAP.put(spName, spUtils);
        }
        return spUtils;
    }

    /**
     * SP 中读取 String
     *
     * @param key 键
     * @return 存在返回对应值，不存在返回默认值{@code ""}
     */
    public String getString(final String key) {
        return getString(key, "");
    }

    /**
     * SP 中读取 String
     *
     * @param key 键
     * @param defaultValue 默认值
     * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
     */
    public String getString(final String key, final String defaultValue) {
        return sp.getString(key, defaultValue);
    }

    /**
     * SP 中读取 int
     *
     * @param key 键
     * @return 存在返回对应值，不存在返回默认值-1
     */
    public int getInt(final String key) {
        return getInt(key, -1);
    }

    /**
     * SP 中读取 int
     *
     * @param key 键
     * @param defaultValue 默认值
     * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
     */
    public int getInt(final String key, final int defaultValue) {
        return sp.getInt(key, defaultValue);
    }

    /**
     * SP 中写入 String
     *
     * @param key 键
     * @param value 值
     */
    public void put(final String key, final String value) {
        put(key, value, false);
    }

    /**
     * SP 中写入 String
     *
     * @param key 键
     * @param value 值
     * @param isCommit {@code true}: {@link Preferences#flushSync()}<br>
     * {@code false}: {@link Preferences#flush()}
     */
    public void put(final String key,
                    final String value,
                    final boolean isCommit) {
        if (isCommit) {
            sp.putString(key, value).flushSync();
        } else {
            sp.putString(key, value).flush();
        }
    }

    /**
     * SP 中写入 int
     *
     * @param key 键
     * @param value 值
     */
    public void put(final String key, final int value) {
        put(key, value, false);
    }

    /**
     * SP 中写入 int
     *
     * @param key 键
     * @param value 值
     * @param isCommit {@code true}: {@link Preferences#flushSync()}<br>
     * {@code false}: {@link Preferences#flush()}
     */
    public void put(final String key, final int value, final boolean isCommit) {
        if (isCommit) {
            sp.putInt(key, value).flushSync();
        } else {
            sp.putInt(key, value).flush();
        }
    }

    /**
     * SP 中写入 long
     *
     * @param key 键
     * @param value 值
     */
    public void put(final String key, final long value) {
        put(key, value, false);
    }

    /**
     * SP 中写入 long
     *
     * @param key 键
     * @param value 值
     * @param isCommit {@code true}: {@link Preferences#flushSync()} ()}<br>
     * {@code false}: {@link Preferences#flush()} ()}
     */
    public void put(final String key, final long value, final boolean isCommit) {
        if (isCommit) {
            sp.putLong(key, value).flushSync();
        } else {
            sp.putLong(key, value).flush();
        }
    }

    /**
     * SP 中写入 float
     *
     * @param key 键
     * @param value 值
     */
    public void put(final String key, final float value) {
        put(key, value, false);
    }

    /**
     * SP 中写入 float
     *
     * @param key 键
     * @param value 值
     * @param isCommit {@code true}: {@link Preferences#flushSync()}<br>
     * {@code false}: {@link Preferences#flush()}
     */
    public void put(final String key, final float value, final boolean isCommit) {
        if (isCommit) {
            sp.putFloat(key, value).flushSync();
        } else {
            sp.putFloat(key, value).flush();
        }
    }

    /**
     * SP 中写入 boolean
     *
     * @param key 键
     * @param value 值
     */
    public void put(final String key, final boolean value) {
        put(key, value, false);
    }

    /**
     * SP 中写入 boolean
     *
     * @param key 键
     * @param value 值
     * @param isCommit {@code true}: {@link Preferences#flushSync()}<br>
     * {@code false}: {@link Preferences#flush()}
     */
    public void put(final String key, final boolean value, final boolean isCommit) {
        if (isCommit) {
            sp.putBoolean(key, value).flushSync();
        } else {
            sp.putBoolean(key, value).flush();
        }
    }

    /**
     * SP 中写入 String 集合
     *
     * @param key 键
     * @param values 值
     */
    public void put(final String key, final Set<String> values) {
        put(key, values, false);
    }

    /**
     * SP 中写入 String 集合
     *
     * @param key 键
     * @param values 值
     * @param isCommit {@code true}: {@link Preferences#flushSync()}<br>
     * {@code false}: {@link Preferences#flush()}
     */
    public void put(final String key,
                    final Set<String> values,
                    final boolean isCommit) {
        if (isCommit) {
            sp.putStringSet(key, values).flushSync();
        } else {
            sp.putStringSet(key, values).flush();
        }
    }

    /**
     * SP 中读取 long
     *
     * @param key 键
     * @return 存在返回对应值，不存在返回默认值-1
     */
    public long getLong(final String key) {
        return getLong(key, -1L);
    }

    /**
     * SP 中读取 long
     *
     * @param key 键
     * @param defaultValue 默认值
     * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
     */
    public long getLong(final String key, final long defaultValue) {
        return sp.getLong(key, defaultValue);
    }

    /**
     * SP 中读取 float
     *
     * @param key 键
     * @return 存在返回对应值，不存在返回默认值-1
     */
    public float getFloat(final String key) {
        return getFloat(key, -1f);
    }

    /**
     * SP 中读取 float
     *
     * @param key 键
     * @param defaultValue 默认值
     * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
     */
    public float getFloat(final String key, final float defaultValue) {
        return sp.getFloat(key, defaultValue);
    }

    /**
     * SP 中读取 boolean
     *
     * @param key 键
     * @return 存在返回对应值，不存在返回默认值{@code false}
     */
    public boolean getBoolean(final String key) {
        return getBoolean(key, false);
    }

    /**
     * SP 中读取 boolean
     *
     * @param key 键
     * @param defaultValue 默认值
     * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
     */
    public boolean getBoolean(final String key, final boolean defaultValue) {
        return sp.getBoolean(key, defaultValue);
    }

    /**
     * SP 中读取 StringSet
     *
     * @param key 键
     * @return 存在返回对应值，不存在返回默认值{@code Collections.<String>emptySet()}
     */
    public Set<String> getStringSet(final String key) {
        return getStringSet(key, Collections.<String>emptySet());
    }

    /**
     * SP 中读取 StringSet
     *
     * @param key 键
     * @param defaultValue 默认值
     * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
     */
    public Set<String> getStringSet(final String key,
                                    final Set<String> defaultValue) {
        return sp.getStringSet(key, defaultValue);
    }

    /**
     * SP 中获取所有键值对
     *
     * @return Map 对象
     */
    public Map<String, ?> getAll() {
        return sp.getAll();
    }

    /**
     * SP 中是否存在该 key
     *
     * @param key 键
     * @return {@code true}: 存在<br>{@code false}: 不存在
     */
    public boolean contains(final String key) {
        return sp.hasKey(key);
    }

    /**
     * SP 中移除该 key
     *
     * @param key 键
     */
    public void remove(final String key) {
        remove(key, false);
    }

    /**
     * SP 中移除该 key
     *
     * @param key 键
     * @param isCommit {@code true}: {@link Preferences#flushSync()}<br>
     * {@code false}: {@link Preferences#flush()}
     */
    public void remove(final String key, final boolean isCommit) {
        if (isCommit) {
            sp.delete(key).flushSync();
        } else {
            sp.delete(key).flush();
        }
    }

    /**
     * SP 中清除所有数据
     */
    public void clear() {
        clear(false);
    }

    /**
     * SP 中清除所有数据
     *
     * @param isCommit {@code true}: {@link Preferences#flushSync()}<br>
     * {@code false}: {@link Preferences#flush()}
     */
    public void clear(final boolean isCommit) {
        if (isCommit) {
            sp.clear().flushSync();
        } else {
            sp.clear().flush();
        }
    }

    private static boolean isSpace(final String s) {
        if (s == null) {
            return true;
        }
        for (int i = 0, len = s.length(); i < len; ++i) {
            if (!Character.isWhitespace(s.charAt(i))) {
                return false;
            }
        }
        return true;
    }
}
